package com.rightsidetech.commom.utils;
import ch.qos.logback.core.encoder.ByteArrayUtil;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
 * @Author: yhr
 * @Date: 2021-12-24 14:14
 */
public class ByteUtil {
    /**
     * int转1位长度的byte[]（大端在前，小端在后）
     * 小端
     *
     * @param len
     * @return
     */
    public static byte[] intToByte(int len) {
        byte[] targets = new byte[1];
        targets[0] = (byte) (len & 0xFF);
//        targets[1] = (byte) (len >> 8 & 0xFF);
        return targets;
    }

    /**
     * 大端
     */
    public static byte[] intToByteB(int len) {
        byte[] targets = new byte[2];
        targets[1] = (byte) (len & 0xFF);
        targets[0] = (byte) (len >> 8 & 0xFF);
        return targets;
    }

    /**
     * 2位byte[]求长度
     *
     * @param len
     * @return
     */
    public static int byteToInt(byte[] len) {
        return len[0] << 8 | len[1] & 0xFF;
    }

    /**
     * 2位byte[]转换成int,适用于(高位在前，低位在后)的顺序
     *
     * @param pos
     * @return
     */
    public static int byteToInt(byte[] data, int pos) {
        return data[pos] << 8 | data[pos + 1] & 0xFF;
    }

    /**
     * 2位byte[]转换成int,适用于(低位在前，高位在后)的顺序
     */
//    public static int byteToInt2(byte[] data, int pos) {
//        return data[pos + 1] << 8 | data[pos] & 0xFF;
//    }
    public static int bytesToInt2(byte[] ary, int offset) {
        int value;
        value = (ary[offset] & 0xFF);
        return value;
    }


    /**
     * 2位byte[]求长度
     *
     * @param pos
     * @return
     */
    public static int byteToIntConvert(byte[] data, int pos) {
        return data[pos + 1] << 8 | data[pos] & 0xFF;
    }

    /**
     * 一个byte 转int，无符号
     *
     * @param b
     * @return
     */
    public static int byteToInt(byte b) {
        return b & 0xFF;
    }

    /**
     * 获取string类型数据
     *
     * @param bytes
     * @param pos
     * @param len
     * @return
     */
    public static String getString(byte[] bytes, int pos, int len) {
        try {
            return new String(bytes, pos, len, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return "";
        }
    }

    /**
     * 获取string类型数据
     *
     * @param bytes
     * @return
     */
    public static String getString(byte[] bytes) {
        return getString(bytes, 0, bytes.length);
    }

    /**
     * byte取前4位
     *
     * @param b
     * @return
     */
    public static int getLeft(byte b) {
        return b >> 4 & 15;
    }

    /**
     * byte取后4位
     *
     * @param b
     * @return
     */
    public static int getRight(byte b) {
        return b & 15;
    }

    /**
     * byte截取
     *
     * @param b
     * @param pos
     * @param len
     * @return
     */
    public static String subString(int b, int pos, int len) {
        String s = Integer.toBinaryString(b);
        String str = String.format("%08d", Integer.valueOf(s));
        return str.substring(pos, len + pos);
    }

    /**
     * 获取01字符串
     *
     * @param b
     * @return
     */
    public static String getBinaryString(int b) {
        String s = Integer.toBinaryString(b);
        return String.format("%08d", Integer.valueOf(s));
    }

    /**
     * 叫数据的位数，前四位掉换成后四bit位
     *
     * @param a
     * @return
     */
    public static byte swap(byte a) {
        int lowBit = a & 0xF;
        int highBit = a & 0xF0;
        return (byte) (lowBit << 4 | highBit >>> 4);
    }

    /**
     * 将int数值转换为占四个字节的byte数组，本方法适用于(低位在前，高位在后)的顺序。
     *
     * @param value 要转换的int值
     * @return byte数组
     */
    public static byte[] intToBytes(int value) {
        byte[] byteSrc = new byte[4];
        byteSrc[3] = (byte) ((value & 0xFF000000) >> 24);
        byteSrc[2] = (byte) ((value & 0x00FF0000) >> 16);
        byteSrc[1] = (byte) ((value & 0x0000FF00) >> 8);
        byteSrc[0] = (byte) ((value & 0x000000FF));
        return byteSrc;
    }

    /**
     * byte数组中取int数值，本方法适用于(低位在前，高位在后)的顺序。
     *
     * @param ary    byte数组
     * @param offset 从数组的第offset位开始
     * @return int数值
     */
    public static int bytesToInt(byte[] ary, int offset) {
        int value;
        value = ((ary[offset] & 0xFF)
                | ((ary[offset + 1] << 8) & 0xFF00)
                | ((ary[offset + 2] << 16) & 0xFF0000)
                | ((ary[offset + 3] << 24) & 0xFF000000));
        return value;
    }

    public static int getIntFromBytes(byte high_h, byte high_l, byte low_h, byte low_l) {
        return (high_h & 0xff) << 24 | (high_l & 0xff) << 16 | (low_h & 0xff) << 8 | low_l & 0xff;
    }

    /**
     * dword转long
     *
     * @param data
     * @param offset
     * @return
     */
    public static long getLongFromDword(byte[] data, int offset) {
        return (data[offset] & 0xff) << 24 | (data[offset + 1] & 0xff) << 16 | (data[offset + 2] & 0xff) << 8 | data[offset + 3] & 0xff;
    }

    public static byte[] swapByteArray(byte[] bytes) {
        byte tmp = 0;
        tmp = bytes[0];
        bytes[0] = bytes[1];
        bytes[1] = tmp;
        return bytes;
    }

    /**
     * 把byte转为字符串的bit
     */
    public static String byteToStringBit(byte b) {
        return ""
                + (byte) ((b >> 7) & 0x1) + (byte) ((b >> 6) & 0x1)
                + (byte) ((b >> 5) & 0x1) + (byte) ((b >> 4) & 0x1)
                + (byte) ((b >> 3) & 0x1) + (byte) ((b >> 2) & 0x1)
                + (byte) ((b >> 1) & 0x1) + (byte) ((b >> 0) & 0x1);
    }

    /**
     * 将一个字节的byte转换为一个长度为8的byte数组，数组每个值代表一个bit
     */
    public static byte[] getBitArray(byte b) {
        byte[] array = new byte[8];
        for (int i = 7; i >= 0; i--) {
            array[i] = (byte) (b & 1);
            b = (byte) (b >> 1);
        }
        return array;
    }

    //    public static String bytesToString(byte[] ary, int offset) {
//        String value;
//        value = ary[offset + 1];
//        return value;
//    }
    public static void main(String[] args) {
//        byte[] data = new byte[8];
//        System.arraycopy(ByteUtil.intToByte(32767), 0, data, 3, 2);
//        System.out.println(bytesToInt2(data,3));
//        System.out.println(byteToInt2(data,3));
//        System.out.println(ByteArrayUtil.toHexString(intToByteB(670)));
        System.out.println(bytesToInt(ByteArrayUtil.hexStringToByteArray("02000000"), 0));
        //System.out.println(bytesToInt2("e50c".getBytes(), 0));
        System.out.println(bytesToLong(ByteArrayUtil.hexStringToByteArray("027407b300000000"), 0, true));
        byte[] bytes = new byte[8];
        System.arraycopy(ByteArrayUtil.hexStringToByteArray("027407b3"), 0, bytes, 0, 4);
        System.out.println(bytesToLong(bytes, 0, true));

    }

    public static long bytesToLong(byte[] input, int offset, boolean littleEndian) {
        // 将byte[] 封装为 ByteBuffer
        ByteBuffer buffer = ByteBuffer.wrap(input, offset, 8);
        if (littleEndian) {
            // ByteBuffer.order(ByteOrder) 方法指定字节序,即大小端模式(BIG_ENDIAN/LITTLE_ENDIAN)
            // ByteBuffer 默认为大端(BIG_ENDIAN)模式
            buffer.order(ByteOrder.LITTLE_ENDIAN);
        }
        return buffer.getLong();
    }


    /**
     * 不够位数的在前面补0，保留num的长度位数字
     * @param code
     * @return
     */
    public static String autoGenericCode(String code, int num) {
        // 保留num的位数
        // 0 代表前面补充0
        // num 代表长度为4
        // d 代表参数为正数型
        String result = String.format("%0" + num + "d", Integer.parseInt(code) + 1);

        return result;
    }

    /**
     * 向串口发送数据转为字节数组
     */
    public static byte[] hex2byte(String hex) {
        String digital = "0123456789ABCDEF";
        String hex1 = hex.replace(" ", "").toUpperCase();
        char[] hex2char = hex1.toCharArray();
        byte[] bytes = new byte[hex1.length() / 2];
        byte temp;
        for (int p = 0; p < bytes.length; p++) {
            temp = (byte) (digital.indexOf(hex2char[2 * p]) * 16);
            temp += digital.indexOf(hex2char[2 * p + 1]);
            bytes[p] = (byte) (temp & 0xff);
        }
        return bytes;
    }

    /**
     * 接收到的字节数组转换16进制字符串
     */
    public static String byteToStr(byte[] b, int size) {
        String ret = "";
        for (int i = 0; i < size; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret += hex.toUpperCase();
        }
        return ret;
    }



    public static String format(int hex) {
        String hexa = Integer.toHexString(hex);
        int len = hexa.length();
        if (len < 2) {
            hexa = "0" + hexa;
        }
        return hexa;
    }

    public static String getBCC(String hex) {
        int i = 0, j = 0;
        int len = hex.length();
        short inb[] = new short[len];
        for (i = 0; i < len; i++) {
            inb[i] = charToHex(hex.charAt(i));   //将String里的每一个char转换为Hex
        }

        for (i = 0; i < len; i++) {    //将每两个Hex合并成一个byte
            inb[j] = (byte) (((inb[i] << 4) & 0x00f0) | ((inb[i + 1]) & 0x000f));
            i++;
            j++;
        }
        byte temp = 0x00; //校验值
        for (i = 0; i < len / 2; i++) { //异或
            temp ^= inb[i];
        }
        byte[] bytes = new byte[1];
        bytes[0] = temp;
        return ByteUtil.byteToStr(bytes, bytes.length);
    }

    public static short charToHex(char x) { //将单个char转换为Hex
        short result = 0;
        switch (x) {
            case 'a':
                result = 10;
                break;
            case 'b':
                result = 11;
                break;
            case 'c':
                result = 12;
                break;
            case 'd':
                result = 13;
                break;
            case 'e':
                result = 14;
                break;
            case 'f':
                result = 15;
                break;
            case 'A':
                result = 10;
                break;
            case 'B':
                result = 11;
                break;
            case 'C':
                result = 12;
                break;
            case 'D':
                result = 13;
                break;
            case 'E':
                result = 14;
                break;
            case 'F':
                result = 15;
                break;
            default:
                result = (short) Character.getNumericValue(x);
                break;
        }
        return result;
    }


}
